package com.pi;

import org.apache.catalina.Context;
import org.apache.catalina.connector.Connector;
import org.apache.tomcat.util.descriptor.web.SecurityCollection;
import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
import org.hibernate.validator.HibernateValidator;
import org.mybatis.spring.annotation.MapperScan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.boot.context.event.ApplicationFailedEvent;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.boot.context.event.ApplicationStartingEvent;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;

import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;

/**
 * Stroop启动模块
 * mvn spring-boot:run -Drun.jvmArguments="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005"
 *
 * @author chenmfa@163.com
 */
@SpringBootApplication
@ServletComponentScan
@ComponentScan("com.pi")
@MapperScan(basePackages = {"com.pi"})
//@EnableAutoConfiguration
//@EnableRedisHttpSession
public class StroopBootStrap {

    public static final Logger LOGGER = LoggerFactory.getLogger(StroopBootStrap.class);

    @Value("${server.port}")
    private int httpsPort;
    @Value("${server.http.port}")
    private int httpPort;

    public static void main(String[] args) {
//    {@link org.springframework.boot.context.event.ApplicationStartingEvent} springboot启动开始时执行的事件
//    {@link org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent}spring boot 对应Enviroment已经准备完毕，但此时上下文context还没有创建。
//    {@link org.springframework.boot.context.event.ApplicationFailedEvent} spring boot启动异常时执行事件 
        SpringApplication application = new SpringApplication(StroopBootStrap.class);
        application.addListeners((ApplicationListener<ApplicationEnvironmentPreparedEvent>) event ->
                LOGGER.info("----------------- Spring 环境首次初始化成功： -----------------------------"));
        application.addListeners((ApplicationListener<ApplicationStartingEvent>) event ->
                LOGGER.info("----------------- Spring Boot 应用正在启动： -----------------------------"));
        application.addListeners((ApplicationListener<ApplicationReadyEvent>) event -> {

        });
        application.addListeners((ApplicationListener<ApplicationFailedEvent>) event ->
                LOGGER.info("----------------- Spring Boot应用启动失败： {}", event.getException().toString()));
        application.run(args);
    }

    @Bean
    public EmbeddedServletContainerFactory servletContainer() {
        TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory() {
            @Override
            protected void postProcessContext(Context context) {
                SecurityConstraint constraint = new SecurityConstraint();
                //CONFIDENTIAL
                constraint.setUserConstraint("NONE");
                SecurityCollection collection = new SecurityCollection();
                collection.addPattern("/*");
                constraint.addCollection(collection);
                context.addConstraint(constraint);
            }
        };
        tomcat.addAdditionalTomcatConnectors(httpConnector());
        return tomcat;
    }

    //  配置文件配置了https端口,这里配置http端口
    @Bean
    public Connector httpConnector() {
        Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
        connector.setScheme("https");
        connector.setPort(httpPort);
        connector.setSecure(false);
        connector.setRedirectPort(httpsPort);
        return connector;
    }

    //  配置validator为快速验证(因为默认会返回所有错误消息，这个是没必要的)
    @Bean
    public Validator validator() {
        //.addProperty("hibernate.validator.fail_fast", "true")
        ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class)
                .configure().failFast(true)
                .buildValidatorFactory();
        return validatorFactory.getValidator();
    }
}
